package kernel

import (
	. "data/datatype"
	"data/entity"
	"util/log"
)

type Kernel struct {
	f        *factory
	regionid int32
}

func (k *Kernel) create(t string, capacity int) (GameObjecter, ObjectID) {

	tp := Type(t)
	if tp == 0 {
		log.LogError("type not found")
		return nil, ObjectID{}
	}

	if tp == PLAYER || tp == SCENE {
		log.LogError("player or scene can't create")
		return nil, ObjectID{}
	}

	newobj, id := k.f.Create(t)
	if newobj == nil {
		log.LogError("create object failed, ", t)
		return nil, ObjectID{}
	}

	newobj.SetKernel(k)
	newobj.SetCapacity(capacity)
	newobj.OnCreate()

	return newobj, *id
}

func (k *Kernel) Create(t string) ObjectID {
	_, id := k.create(t, -1)
	return id
}

func (k *Kernel) CreateGameObjecter(t string, capacity int) ObjectID {
	if capacity < 0 {
		return ObjectID{}
	}

	_, id := k.create(t, capacity)

	return id
}

func (k *Kernel) DestroySelf(id ObjectID) {
	obj := k.f.GetObject(id)

	if obj != nil {

		dt := obj.GetDataType()

		t := entity.GetType(dt)
		if t == 0 {
			log.LogError("type not found")
			return
		}

		if t == PLAYER || t == SCENE {
			log.LogError("player or scene can't destroy")
			return
		}

		obj.OnDestroy()

		k.f.Delete(id)
	}
}

func (k *Kernel) addChild(parent GameObjecter, child GameObjecter, index int) int {

	if child.Parent() != nil {
		k.RemoveChild(child.Parent(), child)
	}

	res := parent.OnTestAdd(child)

	if res != 1 {
		return -1
	}

	res = parent.AddChild(index, child)

	if res != -1 {
		parent.OnAdd(child)
		child.OnEntry(parent)
	}

	return res
}

func (k *Kernel) RemoveChild(parent GameObjecter, child GameObjecter) bool {
	if child.Parent() == parent {

		if parent.RemoveChild(child) {
			parent.OnRemove(child)
			child.OnLeave(parent)
			return true
		}
	}

	return false
}

func (k *Kernel) Shutdown() {
	k.f.DeleteAll()
	k.f.ClearDelete()
}

func CreateKernel(regionid int32) *Kernel {
	k := &Kernel{}
	k.f = CreateFactory(regionid)
	k.f.SetKernel(k)
	k.regionid = regionid
	return k
}
